package com.ruoyi.business.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.enums.AccountOpType;
import com.ruoyi.business.enums.OrderStatus;
import com.ruoyi.business.param.MsgPayResult;
import com.ruoyi.business.response.ErrorResponseData;
import com.ruoyi.business.response.ResponseData;
import com.ruoyi.business.response.SuccessResponseData;
import com.ruoyi.business.service.*;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServerExceptionEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能描述
 *
 * @author: scott
 * @date: 2022年06月15日 22:57
 */
@Service
public class ChargeServiceImpl implements ChargeService {

    @Resource
    private ITRecipientInfoService recipientInfoService;

    @Resource
    private ITAccountInfoService accountInfoService;

    @Resource
    private ITAccountLogService accountLogService;

    @Resource
    private ITOrderInfoService orderInfoService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ITUserChannelService userChannelService;
    @Resource
    private ITPayChannelService payChannelService;

    @Autowired
    private ISysConfigService iSysConfigService;

    private static final Logger logger = LoggerFactory.getLogger(ChargeServiceImpl.class);

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED,rollbackFor = Exception.class)
    public ResponseData updateOrderPayResult(boolean failRetry, long orderId,
                                             MsgPayResult msgPayResult, boolean manualSucc) throws Exception {

        logger.info("先检查支付结果.." + msgPayResult);
        boolean takeFeeSucc = false;
        boolean takePlatformFeeSucc = false;
        boolean takeAgentsFeeSucc = false;
        boolean updateSucc = false;
        TOrderInfo orderInfo = null;
        TRecipientInfo userRecipientInfo = null;


        orderInfo = orderInfoService.selectTOrderInfoById(orderId);
        TPayChannel payChannel =  payChannelService.selectTPayChannelByCode(orderInfo.getChannel());
        Date billTime = new Date();
        orderInfo.setPaySuccTime(new Date());
        if (StringUtils.isNotBlank(msgPayResult.getBillTime())) {
            billTime = DateUtils.parseDate(msgPayResult.getBillTime());
            orderInfo.setPaySuccTime(billTime);
        }
        // 订单不存在
        if (orderInfo == null) {
            return new ErrorResponseData(ServerExceptionEnum.NOTEXIST_ORDER.getCode(),ServerExceptionEnum.NOTEXIST_ORDER.getMessage());

        }
        if (failRetry == false && orderInfo.getStatus() != OrderStatus.WAIT_PAY.getCode() && payChannel.getReqType().equals("1") ) {
            logger.warn("订单{}不是待支付状态。", orderInfo.getId());
            return new ErrorResponseData(ServerExceptionEnum.ORDER_STATUS_ERROR.getCode(),ServerExceptionEnum.ORDER_STATUS_ERROR.getMessage());
        }
        if(orderInfo.getStatus()==OrderStatus.PAY_SUCC.getCode()){
            logger.warn("订单{}已支付成功。重发通知", orderInfo.getId());

            this.notifyUserPaySucc(orderId);
            return new SuccessResponseData(orderInfo);
        }
        if(failRetry==true){
            orderInfo.setManualSucc(1);
        }
        orderInfo.setUpdateUser(msgPayResult.getUpdateUser());
        orderInfo.setMsgPayResult(msgPayResult.getChannelPayMsgResult());
        orderInfo.setPay3rdOrderNo(msgPayResult.getOrderId());

        /**
         * 收取平台手续费 固定只有余额扣减模式
         */
        userRecipientInfo = recipientInfoService.selectTRecipientInfoById(orderInfo.getRecipientId());
        if (orderInfo.getPlatformFee() > 0) {

//                Long feeUid = orderInfo.getPlatformFeeUid();
//                // 兼容老版本数据，从收款号所有人收取
//                if( feeUid==null || feeUid == 0){
//                    feeUid = userRecipientInfo.getUserId();
//                }
//                takePlatformFeeSucc = accountService.takePlatformFee(orderInfo.getId(),
//                        feeUid, orderInfo.getPlatformFee());
//                if(takePlatformFeeSucc){
//                    // 更新已收手续费
//                    orderInfoDao.updateRealFee(orderInfo.getId());
//                }
        } else {
            takePlatformFeeSucc = true;
        }

        logger.info("订单{}计算平台服务费结果：{}", orderInfo.getId(), takePlatformFeeSucc);
        TUserChannel qryUserChannel = new TUserChannel();
        qryUserChannel.setUserId(orderInfo.getUserId());
        qryUserChannel.setChannel(orderInfo.getChannel());
        TUserChannel userChannel = userChannelService.selectTUserChannelListByNoAuth(qryUserChannel).get(0);
        orderInfo.setStatus(OrderStatus.PAY_SUCC.getCode());
        orderInfo.setReceiptMoney(orderInfo.getRealMoney()*(10000-userChannel.getUserRate())/10000);
        orderInfoService.updateTOrderInfo(orderInfo);
        logger.info("订单校验通过！准备更新订单支付结果.." + msgPayResult);

        //修改收款账信息
//        if(!userRecipientInfo.getChannel().equalsIgnoreCase("alipay_cez_h5")){
//        }
        userRecipientInfo.setTodayCount(userRecipientInfo.getTodayCount()==null?0:userRecipientInfo.getTodayCount()+1);
        userRecipientInfo.setTodayMoney(userRecipientInfo.getTodayMoney()+orderInfo.getRealMoney());
        userRecipientInfo.setTotalCount(userRecipientInfo.getTotalCount()==null?0:userRecipientInfo.getTotalCount()+1);
        userRecipientInfo.setTotalMoney(userRecipientInfo.getTotalMoney()+orderInfo.getRealMoney());
        recipientInfoService.updateTRecipientInfo(userRecipientInfo);
        TAccountInfo queryAccountInfo = new TAccountInfo();
        queryAccountInfo.setUserId(orderInfo.getUserId());
        TAccountInfo  accountInfo = accountInfoService.selectTAccountInfoListByNoAuth(queryAccountInfo).get(0);
        long balance = accountInfo.getBalance() + orderInfo.getMoney()*(10000-orderInfo.getChannelRate())/10000;
        TAccountLog  accountLog = new TAccountLog();
        accountLog.setAccountId(accountInfo.getId());
        accountLog.setUserId(accountInfo.getUserId());
        accountLog.setBizId(orderId);
        accountLog.setOpType(AccountOpType.INCOME_ORDER.getVal());
        accountLog.setOpDesc(String.format(AccountOpType.INCOME_ORDER.getDesc() + "关联订单号【%d】成功增加余额%s元", accountLog.getBizId(),
                MoneyUtil.fenToYuan(String.valueOf(orderInfo.getMoney()))));
        // 操作金额。单位分。正数-收入，负数-支出
        accountLog.setOpAmount(orderInfo.getMoney()*(10000-userChannel.getUserRate())/10000);
        accountLog.setOldAmount(accountInfo.getBalance());
        accountLog.setNewAmount(balance);
        // 流水
        accountLogService.insertTAccountLog(accountLog);
        accountInfo.setBalance(balance);
        accountInfo.setTotalMoney(accountInfo.getTotalMoney() + orderInfo.getRealMoney());
        accountInfo.setTodayMoney(accountInfo.getTodayMoney() + orderInfo.getMoney());
        accountInfo.setTodayIncome(accountInfo.getTodayIncome() + orderInfo.getMoney()*(10000-userChannel.getUserRate())/10000);
        accountInfo.setTotalIncome(accountInfo.getTotalIncome() + orderInfo.getMoney()*(10000-userChannel.getUserRate())/10000);
        accountInfo.setTodayExpend(accountInfo.getTodayExpend() + orderInfo.getMoney()*userChannel.getUserRate()/10000);
        accountInfo.setTotalExpend(accountInfo.getTotalExpend() + orderInfo.getMoney()*userChannel.getUserRate()/10000);
        accountInfoService.updateTAccountInfo(accountInfo);
        logger.info("订单{} 金额：{}，新增完商户余额：{}", orderInfo.getId(), orderInfo.getMoney(), balance);
        if(payChannel.getReqType()==1){
            //扣除码商余额
            SysUser msUser = sysUserService.selectUserById(orderInfo.getRecipientUid());
            queryAccountInfo = new TAccountInfo();
            queryAccountInfo.setUserId(msUser.getUserId());
            accountInfo = accountInfoService.selectTAccountInfoListByNoAuth(queryAccountInfo).get(0);
            balance = accountInfo.getBalance() - orderInfo.getMoney();
            accountLog = new TAccountLog();
            accountLog.setAccountId(accountInfo.getId());
            accountLog.setUserId(accountInfo.getUserId());
            accountLog.setBizId(orderId);
            accountLog.setOpType(AccountOpType.INCOME_ORDER.getVal());
            accountLog.setOpDesc(String.format(AccountOpType.INCOME_ORDER.getDesc() + "关联订单号【%d】成功扣除余额%s元", accountLog.getBizId(),
                    MoneyUtil.fenToYuan(String.valueOf(orderInfo.getMoney()))));
            // 操作金额。单位分。正数-收入，负数-支出
            accountLog.setOpAmount(orderInfo.getMoney() * -1);
            accountLog.setOldAmount(accountInfo.getBalance());
            accountLog.setNewAmount(balance);
            // 流水
            accountLogService.insertTAccountLog(accountLog);
            accountInfo.setBalance(balance);
            accountInfo.setTodayMoney(accountInfo.getTotalMoney() + orderInfo.getMoney());
            accountInfo.setTodayExpend(accountInfo.getTodayExpend() + orderInfo.getMoney());
            accountInfo.setTotalExpend(accountInfo.getTotalExpend() + orderInfo.getMoney());
            accountInfoService.updateTAccountInfo(accountInfo);
            logger.info("订单{} 金额：{}，扣除完码商余额：{}", orderInfo.getId(), orderInfo.getMoney(), balance);

            //新增码商分润

            TUserChannel userChannelParam = new TUserChannel();
            userChannelParam.setUserId(orderInfo.getRecipientUid());
            userChannelParam.setChannel(orderInfo.getChannel());
            TUserChannel qryRes = userChannelService.selectTUserChannelListByNoAuth(userChannelParam).get(0);
            balance = accountInfo.getBalance() + orderInfo.getMoney()*qryRes.getUserRate()/10000;
            long operAmount = orderInfo.getMoney() * qryRes.getUserRate()/10000;
            if(operAmount>0){
                accountLog = new TAccountLog();
                accountLog.setAccountId(accountInfo.getId());
                accountLog.setUserId(accountInfo.getUserId());
                accountLog.setBizId(orderId);
                accountLog.setOpType(AccountOpType.FEE_ORDER.getVal());
                accountLog.setOpDesc(String.format(AccountOpType.FEE_ORDER.getDesc() + "关联订单号【%d】成功增加余额%s元", accountLog.getBizId(),
                        MoneyUtil.fenToYuan((orderInfo.getMoney() * qryRes.getUserRate()/10000)+"")));
                // 操作金额。单位分。正数-收入，负数-支出
                accountLog.setOpAmount(orderInfo.getMoney() * qryRes.getUserRate()/10000);
                accountLog.setOldAmount(accountInfo.getBalance());
                accountLog.setNewAmount(balance);
                // 流水
                accountLogService.insertTAccountLog(accountLog);
            }
            accountInfo.setBalance(balance);
            accountInfo.setTodayMoney(accountInfo.getTotalMoney() + orderInfo.getMoney() * qryRes.getUserRate()/10000);
            accountInfo.setTodayIncome(accountInfo.getTodayIncome() + orderInfo.getMoney() * qryRes.getUserRate()/10000);
            accountInfo.setTotalIncome(accountInfo.getTotalIncome() + orderInfo.getMoney() * qryRes.getUserRate()/10000);

            accountInfoService.updateTAccountInfo(accountInfo);
            logger.info("订单{} 金额：{}，新增完码商余额：{}", orderInfo.getId(), orderInfo.getMoney()*qryRes.getUserRate()/10000, balance);

            //新增商户余额



            takeAgentsFeeSucc = true;
            logger.info("订单{}计算代理服务费结果：{}", orderInfo.getId(), takeAgentsFeeSucc);
            //计算代理分润
            SysUser parentUser = sysUserService.selectUserById(msUser.getUserParent());
            //循环至商户的代理一级
            while (!parentUser.getMerchantType().equals("-1")){
                //代理收益
                userChannelParam = new TUserChannel();
                userChannelParam.setUserId(parentUser.getUserId());
                userChannelParam.setChannel(orderInfo.getChannel());
                TUserChannel patqryRes = userChannelService.selectTUserChannelListByNoAuth(userChannelParam).get(0);
                //码商费率
                userChannelParam = new TUserChannel();
                userChannelParam.setUserId(msUser.getUserId());
                userChannelParam.setChannel(orderInfo.getChannel());
                qryRes = userChannelService.selectTUserChannelListByNoAuth(userChannelParam).get(0);
                //
                if(parentUser.getMerchantType().equals("1") && parentUser.getUserLevel()==1){//代理
                    //计算代理设置商户的费率-码商费率
                    int shfenruncha = orderInfo.getChannelRate()-qryRes.getUserRate();


                    queryAccountInfo = new TAccountInfo();
                    queryAccountInfo.setUserId(parentUser.getUserId());
                    accountInfo = accountInfoService.selectTAccountInfoListByNoAuth(queryAccountInfo).get(0);

                    balance = accountInfo.getBalance() + orderInfo.getMoney()*shfenruncha/10000;
                    operAmount = orderInfo.getMoney() * shfenruncha / 10000;
                    if(operAmount>0) {
                        accountLog = new TAccountLog();
                        accountLog.setAccountId(accountInfo.getId());
                        accountLog.setUserId(accountInfo.getUserId());
                        accountLog.setBizId(orderId);
                        accountLog.setOpType(AccountOpType.FEE_ORDER.getVal());
                        accountLog.setOpDesc(String.format(AccountOpType.FEE_ORDER.getDesc() + "关联订单号【%d】成功增加余额%s元", accountLog.getBizId(),
                                MoneyUtil.fenToYuan(orderInfo.getMoney() * shfenruncha / 10000 + "")));
                        // 操作金额。单位分。正数-收入，负数-支出
                        accountLog.setOpAmount(orderInfo.getMoney() * shfenruncha / 10000);
                        accountLog.setOldAmount(accountInfo.getBalance());
                        accountLog.setNewAmount(balance);
                        // 流水
                        accountLogService.insertTAccountLog(accountLog);
                    }

                    accountInfo.setBalance(balance);
                    accountInfo.setTodayMoney(accountInfo.getTodayMoney() + orderInfo.getMoney() * shfenruncha/10000);
                    accountInfo.setTodayIncome(accountInfo.getTodayIncome() + orderInfo.getMoney() * shfenruncha/10000);
                    accountInfo.setTotalIncome(accountInfo.getTotalIncome() + orderInfo.getMoney() * shfenruncha/10000);
                    accountInfo.setTotalMoney(accountInfo.getTotalMoney() + orderInfo.getMoney() * shfenruncha/10000);
                    accountInfoService.updateTAccountInfo(accountInfo);
                    logger.info("订单{}为结算到余额模式，准备为{}级代理{}计算收益..", orderInfo.getId(), parentUser.getUserLevel()
                            , parentUser.getUserName());
                }else{
                    int fenruncha = patqryRes.getUserRate()-qryRes.getUserRate();

                    queryAccountInfo = new TAccountInfo();
                    queryAccountInfo.setUserId(parentUser.getUserId());
                    accountInfo = accountInfoService.selectTAccountInfoListByNoAuth(queryAccountInfo).get(0);
                    balance = accountInfo.getBalance() + orderInfo.getMoney()*fenruncha/10000;
                    operAmount = orderInfo.getMoney() * fenruncha / 10000;
                    if(operAmount>0) {
                        accountLog = new TAccountLog();
                        accountLog.setAccountId(accountInfo.getId());
                        accountLog.setUserId(accountInfo.getUserId());
                        accountLog.setBizId(orderId);
                        accountLog.setOpType(AccountOpType.FEE_ORDER.getVal());
                        accountLog.setOpDesc(String.format(AccountOpType.FEE_ORDER.getDesc() + "关联订单号【%d】成功增加余额%s元", accountLog.getBizId(),
                                MoneyUtil.fenToYuan(orderInfo.getMoney() * fenruncha / 10000 + "")));
                        // 操作金额。单位分。正数-收入，负数-支出
                        accountLog.setOpAmount(orderInfo.getMoney() * fenruncha / 10000);
                        accountLog.setOldAmount(accountInfo.getBalance());
                        accountLog.setNewAmount(balance);
                        // 流水
                        accountLogService.insertTAccountLog(accountLog);
                    }
                    accountInfo.setBalance(balance);
                    accountInfo.setTodayMoney(accountInfo.getTodayMoney() + orderInfo.getMoney() * fenruncha/10000);
                    accountInfo.setTodayIncome(accountInfo.getTodayIncome() + orderInfo.getMoney() * fenruncha/10000);
                    accountInfo.setTotalIncome(accountInfo.getTotalIncome() + orderInfo.getMoney() * fenruncha/10000);
                    accountInfo.setTotalMoney(accountInfo.getTotalMoney() + orderInfo.getMoney() * fenruncha/10000);

                    accountInfoService.updateTAccountInfo(accountInfo);
                    logger.info("订单{}为结算到余额模式，准备为{}级码商{}计算收益..", orderInfo.getId(), parentUser.getUserLevel()
                            , parentUser.getUserName());
                }
                msUser =  sysUserService.selectUserById(msUser.getUserParent());
                parentUser = sysUserService.selectUserById(parentUser.getUserParent());
            }
        }
        //处理完成发送通知
        logger.info("更新订单支付结果成功！准备发送回调通知..{}",orderInfo);
        orderInfo.setPaySucc(1);
        orderInfoService.updateTOrderInfo(orderInfo);
        logger.info("修改订单状态！..{}",orderInfo.getStatus());
        return new SuccessResponseData(orderInfo);
    }

    public void notifyUserPaySucc(long orderId) throws Exception {
        TOrderInfo orderInfo = orderInfoService.selectTOrderInfoById(orderId);
        if( orderInfo.getStatus() != OrderStatus.PAY_SUCC.getCode() ){
            logger.info("订单：{}不是支付成功状态！");
            return;
        }
        if( orderInfo.getNotifySucc()==1){
            logger.info("订单：{}已经回调成功不需要重复通知！");
            return;
        }
        String notifyUrl = orderInfo.getNotifyUrl();
        // 开始回调
        // 设置参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("channel",orderInfo.getChannel());
        paramMap.put("tradeNo",String.valueOf(orderInfo.getId()));
        paramMap.put("outTradeNo",orderInfo.getOutTradeNo());
        paramMap.put("money", MoneyUtil.fenToYuan(orderInfo.getMoney().toString()));
        paramMap.put("realMoney",MoneyUtil.fenToYuan(orderInfo.getRealMoney().toString()));
        paramMap.put("uid",orderInfo.getUserId().toString());
        if(orderInfo.getOutUserId()!=null){
            paramMap.put("outUserId",orderInfo.getOutUserId());
        }
        if(orderInfo.getOutBody()!=null){
            paramMap.put("outBody",orderInfo.getOutBody());
        }

        // 签名参数
        Map<String,String> signParamMap = new HashMap<>();
        signParamMap.put("channel",orderInfo.getChannel());
        signParamMap.put("tradeNo",String.valueOf(orderInfo.getId()));
        signParamMap.put("outTradeNo",orderInfo.getOutTradeNo());
        signParamMap.put("money",MoneyUtil.fenToYuan(orderInfo.getMoney().toString()));
        signParamMap.put("realMoney",MoneyUtil.fenToYuan(orderInfo.getRealMoney().toString()));
        signParamMap.put("uid",orderInfo.getUserId().toString());
        if(orderInfo.getOutUserId()!=null){
            signParamMap.put("outUserId",orderInfo.getOutUserId());
        }
        if(orderInfo.getOutBody()!=null){
            signParamMap.put("outBody",orderInfo.getOutBody());
        }
        String token = sysUserService.selectUserById(orderInfo.getUserId()).getToken();
        String sign = MD5Util.stringMD5(SignUtil.formatUrlMap(signParamMap,false)+"&key="+token);

        paramMap.put("sign",sign);
        signParamMap.clear();

        int retryCount = 1;

        logger.info("订单：{} 开始回调地址：{}，回调参数>>>{}",orderId,notifyUrl,paramMap);
        String result = HttpUtils.sendPostRequest(notifyUrl,SignUtil.formatUrlMap(paramMap,true));

        logger.info("订单：{}回调结果：{}",orderInfo.getId(),result);
        // 回调接口返回字符串大写SUCCESS才表示成功。否则需要重发通知。
        // 最多3次。每次间隔 (retryCount - 1)*300 + 10 秒
        // 1s，5分钟，10分钟
        while( !(result.equals("OK") || result.equalsIgnoreCase("success"))  && retryCount < 3 ){
            logger.warn("订单：{}，准备第{}次重发通知..",orderInfo.getId(),retryCount);
            int sleepSenconds = (retryCount - 1)*3 + 2;
            Thread.sleep(sleepSenconds*1000);
//            result = restTemplate.postForObject(notifyUrl,
//                    paramMap,String.class);
            result = HttpUtils.sendPost(notifyUrl,SignUtil.formatUrlMap(paramMap,true),"");
            logger.info("订单：{}回调结果：{}",orderInfo.getId(),result);
            retryCount++;
        }

        if( !(result.equals("OK") || result.equalsIgnoreCase("success"))  ){
            logger.warn("订单：{}，重发{}次通知后仍然失败！",orderInfo.getId(),retryCount);
            orderInfo.setNotifySucc(0);
            orderInfoService.updateTOrderInfo(orderInfo);
            throw new ServiceException(ServerExceptionEnum.NOTIFY_FAIL.getMessage());
        }
        logger.warn("订单：{} 通知成功！",orderInfo.getId());
        // 通知成功要更改状态
        orderInfo.setNotifySucc(1);
        orderInfo.setNotifySuccTime(new Date());
        logger.warn("订单：{} 通知成功的状态",orderInfo.getStatus());
        orderInfoService.updateTOrderInfo(orderInfo);
    }

    @Override
    public AjaxResult smartReissueOrder(TOrderInfo orderInfoParam) throws Exception {
        TOrderInfo orderInfo = orderInfoService.selectTOrderInfoById(orderInfoParam.getId());
        long userId = ShiroUtils.getSysUser().getUserId();
        if (orderInfo == null) {
            throw new ServiceException(ServerExceptionEnum.NOTEXIST_ORDER.getMessage());
        }
        if (orderInfo.getStatus() == OrderStatus.PAY_SUCC.getCode()) {
            this.notifyUserPaySucc(orderInfoParam.getId());
            return AjaxResult.success(orderInfo);
        }
//        if (orderInfo.getStatus() != OrderStatus.WAIT_PAY.getCode()
//                && orderInfo.getStatus() != OrderStatus.TIMEOUT.getCode()) {
//            this.notifyUserPaySucc(orderInfoParam.getId());
//            throw new ServiceException(ServerExceptionEnum.NOT_RIGHT_STATUS_ORDER.getMessage());
//
//        }
//        if (orderInfo.getRecipientUid().longValue()!= userId) {
//            throw new ServiceException(ServerExceptionEnum.NOVALID_OP.getMessage());
//        }
        TPayChannel payChannel = payChannelService.selectTPayChannelByCode(orderInfo.getChannel());
        PaymentInterface paymentInterface;
        try {
            paymentInterface = (PaymentInterface) SpringUtils.getBean(payChannel.getAliasName().toLowerCase() + "PayService");
        } catch (BeansException e) {
            logger.info("支付渠道类型[channel=" + payChannel.getChannel() + "]实例化异常");
            return AjaxResult.error(ServerExceptionEnum.CHANNEL_ERROR.getMessage());
        }
        ResponseData responseData = paymentInterface.smartReissueOrder(orderInfo);
        if(responseData.getSuccess()){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(responseData.getMessage());
        }
    }

    @Override
    public AjaxResult testPay(TRecipientInfo tUserRecipientInfo) throws Exception {
        TRecipientInfo tRecipientInfo = recipientInfoService.selectTRecipientInfoById(tUserRecipientInfo.getId());
        if(tRecipientInfo==null){
            return AjaxResult.error("未查询到收款账号");
        }
        Map<String, String> params = new HashMap<String, String>();
        TPayChannel payChannel = payChannelService.selectTPayChannelByCode(tRecipientInfo.getChannel());
        String nginxPayGateway = iSysConfigService.selectConfigByKey("sys.bussine.nginxPayGateway");
        String orderCode = String.valueOf(new Date().getTime());
        params.put("channelType", payChannel.getType());  //根据请求的支付类型不一样， 选择不同的支付方式
        params.put("channel", payChannel.getChannel());
        params.put("nonce_str", orderCode);
        params.put("uid", "105");  //根据平台分配的merchantid, 替换配置
        params.put("outTradeNo", orderCode);   //商家系统的订单号， 请保持再商家系统里面唯一
        params.put("goodsName", "test");    //购买物品的名称
        params.put("money", tUserRecipientInfo.getTestMoney().toString());   //精确到小数点后两位
        params.put("recipientId", tRecipientInfo.getId()+"");   //精确到小数点后两位
        String url = nginxPayGateway + "/demo/pay/callback/" + orderCode;
        System.out.printf("回调地址=======" + url);
        params.put("notifyUrl", url);
        params.put("returnUrl", url);   //精确到小数点后两位
        params.put("timestamp", String.valueOf(new Date().getTime()));
//		params.put("card_no", "6226661700077532");
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        System.out.println("请求网关=======" + preStr + "&key=d2f94d8815eb48af9e1296772c82872a");
        String sign = MD5Util.stringMD5(preStr + "&key=d2f94d8815eb48af9e1296772c82872a");
        params.put("sign", sign.toUpperCase());

        StringBuilder newbuf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(newbuf, params, false);
        String newStr = newbuf.toString();
        System.out.println(newStr);
//        String result =  HttpUtils.sendPost(callBackIpAddress+"smartpayment/pay/gateway",newStr);
        String reqUrl = "";
        reqUrl = nginxPayGateway  + "/api/v1/charges";

        System.out.println("请求网关=======" + reqUrl);

        HttpPost httpPost = new HttpPost(reqUrl);
        StringEntity entity = new StringEntity(newStr, "utf-8");//解决中文乱码问题
        httpPost.setEntity(entity);
        httpPost.addHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded");
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        response = httpClient.execute(httpPost);
        System.out.println(response.getStatusLine().getStatusCode() + "\n");
        HttpEntity result = response.getEntity();
        String responseContent = EntityUtils.toString(result, "UTF-8");
        System.out.println(responseContent);
        JSONObject resultObj = JSONObject.parseObject(responseContent);
        if (resultObj.getString("code").equalsIgnoreCase("200")) {  //标识成功
            Map<String, String> respMap = JSON.parseObject(responseContent, Map.class);
            JSONObject data = resultObj.getJSONObject("data");
            return AjaxResult.success(data.getString("payUrl"));
        } else {
            //异常
            return AjaxResult.error(resultObj.getString("message"));
        }
    }


    @Override
    public ResponseData forcePay(TOrderInfo orderInfoParam) throws Exception {
        TOrderInfo orderInfo = orderInfoService.selectTOrderInfoById(orderInfoParam.getId());
        long userId = ShiroUtils.getSysUser().getUserId();
        if (orderInfo == null) {
            throw new ServiceException(ServerExceptionEnum.NOTEXIST_ORDER.getMessage());
        }
        if (orderInfo.getStatus() == OrderStatus.PAY_SUCC.getCode()) {
            this.notifyUserPaySucc(orderInfoParam.getId());
            return new SuccessResponseData(orderInfo);
        }
        if (orderInfo.getStatus() != OrderStatus.WAIT_PAY.getCode()
                && orderInfo.getStatus() != OrderStatus.TIMEOUT.getCode()) {
            this.notifyUserPaySucc(orderInfoParam.getId());
            throw new ServiceException(ServerExceptionEnum.NOT_RIGHT_STATUS_ORDER.getMessage());

        }
        boolean isAdmin =  ShiroUtils.getSysUser().isAdmin();
        boolean isDataAdmin =  ShiroUtils.getSysUser().isDataAdmin(ShiroUtils.getSysUser().getRoles());
        if (!isAdmin && !isDataAdmin) {
            if (orderInfo.getRecipientUid().longValue()!= userId) {
                throw new ServiceException(ServerExceptionEnum.NOVALID_OP.getMessage());
            }
        }

//        SysUser loginUser = ShiroUtils.getSysUser();

//        if (StringUtils.isEmpty(currentUser.getGoogleKey())) {
//            return new BaseDataJson<>(ResultCodeEnum.GOOGLE_VALID_ERROR);
//        }
//        TPayChannel payChannelParam = new TPayChannel();
//        payChannelParam.setChannel(orderInfo.getChannel());
//        payChannelParam.setType(orderInfo.getChannelType());
//        TPayChannel payChannel = payChannelService.selectTPayChannelList(payChannelParam).get(0);
//        if(payChannel.getNeedGoogle()==1){
//            if(StringUtils.isBlank(loginUser.getGoogleKey())){
//                throw new GoogleException();
//            }
//            GoogleGenerator googleGenerator = new GoogleGenerator();
//            boolean flag = googleGenerator.check_code(loginUser.getGoogleKey(), orderInfoParam.getGoogleCode(), System.currentTimeMillis());
//            if (!flag) {
//                throw new GoogleException();
//            }
//        }
        MsgPayResult msgPayResult = new MsgPayResult();
        msgPayResult.setChannel(orderInfo.getChannel());
        msgPayResult.setTradeNo(orderInfo.getId()+"");
        msgPayResult.setChannelAccount(orderInfo.getChannelAccount());
        msgPayResult.setOrderId("商户" + orderInfo.getUserId() + "人工补单" + orderInfo.getOutTradeNo());
        msgPayResult.setRealMoney(orderInfo.getRealMoney().toString());
        msgPayResult.setUid(orderInfo.getUserId().toString());
        msgPayResult.setUpdateUser(orderInfoParam.getUpdateUser());
        logger.info("准备开始人工补单=======" + JSON.toJSONString(msgPayResult));
        // 异步重新处理订单
       this.updateOrderPayResult(true, orderInfo.getId(), msgPayResult, true);
       this.notifyUserPaySucc(orderInfo.getId());
       return new SuccessResponseData(msgPayResult);
    }

}
